package com.huaxin.dss2.data.NewSmallStation;


import com.github.signalr4j.client.hubs.HubProxy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.huaxin.dss2.data.NewSmallStation.fbox.TokenManager;
import com.huaxin.dss2.data.NewSmallStation.fbox.signalr.SignalRConnectionBase;
import com.huaxin.dss2.data.bean.BoxState;
import com.huaxin.dss2.data.bean.DataValue;
import com.huaxin.dss2.util.Constant;
import com.huaxin.dss2.util.Constant.DMonUpdateValueStatus;
import com.huaxin.dss2.util.Constant.FBoxState;
import com.huaxin.dss2.util.DateParseUtil;
import com.huaxin.dss2.util.JavaUtils;
import com.huaxin.dss2.util.ScheduledValue;
import com.huaxin.dss2.util.SignalRUtils;
import java.net.Proxy;
import java.util.Arrays;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;


@Slf4j
public class FBoxSignalRConnection extends SignalRConnectionBase {

    private final Gson gson;

    private Proxy proxy;


    public FBoxSignalRConnection(String hubUrl, String signalrClientId, TokenManager tokenManager,
        Proxy proxy, com.huaxin.dss2.data.NewSmallStation.fbox.LoggerFactory loggerFactory) {
        super(hubUrl, signalrClientId, tokenManager, proxy, loggerFactory);

        this.proxy = proxy;
        gson = new GsonBuilder().create();
    }


    /**
     * HubProxy代理销毁时进行的操作
     * @param hubProxy HubProxy
     */
    @Override
    protected void onHubProxyDestroyed(HubProxy hubProxy) {
        hubProxy.removeSubscription("dmonUpdateValue");
        hubProxy.removeSubscription("alarmTriggered");
        hubProxy.removeSubscription("alarmRecovered");
        hubProxy.removeSubscription("boxConnStateChanged");
    }
    /**
     * HubProxy代理创建时进行的操作
     * @param hubProxy HubProxy
     */
    @Override
    protected void onHubProxyCreated(HubProxy hubProxy) {

        //当监控点数据发生变化或者开启监控条目时，服务器推送消息
        hubProxy.subscribe("dmonUpdateValue").addReceivedHandler(this::dmonUpdateValue);

        // 当服务器侦测到FBox发生状态变更，则会推送消息
        hubProxy.subscribe("boxConnStateChanged").addReceivedHandler(this::boxConnStateChanged);

        // 当报警条目数据触发报警时，服务器推送消息
        hubProxy.subscribe("alarmTriggered").addReceivedHandler(this::alarmTriggered);

        // 当报警还原时，服务器推送消息
        hubProxy.subscribe("alarmRecovered").addReceivedHandler(this::alarmRecovered);

    }

    /**
     * 当监控点数据发生变化或者开启监控条目时，服务器推送消息
     * @param jsonElements 详见fbox文档 v1.2.2 9.1实时数据推送
     */
    private void dmonUpdateValue(JsonElement[] jsonElements) {
        //首创版本采用过滤站点模式
        JSONArray jo = new JSONArray(jsonElements[1].toString());
        for (int i = 0; i < jo.length(); i++) {
            SDataValue dataValue = new SDataValue();
            JSONObject dataJo = new JSONObject(jo.get(i).toString());
            String name = dataJo.getString("name");
            String[] nameArr = name.split("_");
            if (nameArr.length != Constant.getFullCode().getFracDigitsLength()) {
                continue;
            }

            //判断开启储存站点是否在需要存储中
            if (!ScheduledValue.STATION_CODE_LIST.contains(nameArr[Constant.getFullCode().getStationIndex()])) {
                continue;
            }
            dataValue.setId(dataJo.getString("id"));
            //获取三段名称
            name = SignalRUtils.getFullCode(nameArr);
            dataValue.setName(name);
            dataValue.setDateTime(DateParseUtil.timeToDate(dataJo.get("t").toString()));
            try {
                Double doubleValue = dataJo.getDouble("value");
                dataValue.setValue(doubleValue);
                //将推送的值存入内存中
                ScheduledValue.DATA_VALUE_MAP.put(name, dataValue);
                log.info("{}->{}",dataJo.getString("name"),doubleValue);
            } catch (JSONException e) {
                Integer valueStatus = dataJo.getInt("status");
                log.info("{}->{}",dataJo.getString("name"), DMonUpdateValueStatus.getDesc(valueStatus));
            }
        }
    }

    /**
     * 当服务器侦测到FBox发生状态变更，则会推送消息
     * @param jsonElements 详见fbox文档 v1.2.2 9.4 FBox状态变更推送
     */
    private void boxConnStateChanged(JsonElement[] jsonElements) {
        try {
            if (jsonElements == null || jsonElements.length <= 0) {
                return;
            }
             String fboxStateResult = jsonElements[0].toString();
            if (!JavaUtils.isNullStr(fboxStateResult)) {
                JSONArray fboxStateJsonArray = new JSONArray(fboxStateResult);
                if (fboxStateJsonArray.length() > 0) {
                    //将状态变更的站点进行遍历
                    for (int i = 0; i < fboxStateJsonArray.length(); i++) {
                        JSONObject jo = new JSONObject(fboxStateJsonArray.get(i).toString());
                        String boxUid = jo.getString("id");
                        Integer state = jo.getInt("state");
                        ScheduledValue.F_BOX_STATE_QUEUE.add(new BoxState(boxUid,state));
                        log.info("盒子{}状态变更为{}",jo.getString("id"), FBoxState.getDesc(state));
                    }
                }
            }
        } catch (Exception e) {
            log.error("数据推送出现异常,{}",e.getMessage(),e);
        }
    }
    /**
     * 当报警条目数据触发报警时，服务器推送消息
     * @param jsonElements 详见fbox文档 v1.2.2 9.2 报警触发推送
     */
    private void alarmTriggered(JsonElement[] jsonElements) {
        try {
            if (jsonElements == null || jsonElements.length <= 0) {
                return;
            }
            System.out.println(Arrays.toString(jsonElements));
        } catch (Exception e) {
            log.error("报警触发推送出现异常,{}",e.getMessage(),e);
        }
    }

    /**
     * 当报警条目数据触发报警时，服务器推送消息
     * @param jsonElements 详见fbox文档 v1.2.2 9.2 报警还原推送
     */
    private void alarmRecovered(JsonElement[] jsonElements) {
        try {
            if (jsonElements == null || jsonElements.length <= 0) {
                return;
            }
            System.out.println(Arrays.toString(jsonElements));
        } catch (Exception e) {
            log.error("报警还原推送出现异常,{}",e.getMessage(),e);
        }
    }


    /**
     * 解析json数据
     * @param json json数组
     * @param i 数组index
     * @return DataValue {@link DataValue}
     */
    private DataValue json2DataValue(JSONArray json, int i) {
        DataValue da = null;
        try {
            JSONObject dataJo = new JSONObject(json.get(i).toString());
            String[] nameArr = json2NameArr(json, i);
            String name = SignalRUtils.getFullCode(nameArr);
            Double value = dataJo.getDouble("value");
            da = new DataValue();
            da.setDataCode(name);
            da.setDataValue(value);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return da;
    }

    /**
     * 解析名字出来
     * @param json jsonArray
     * @param i json位
     * @return 解析结果
     */
    private String[] json2NameArr(JSONArray json, int i) {
        JSONObject dataJo = new JSONObject(json.get(i).toString());
        String name = dataJo.getString("name");
        return name.split("_");
    }
}
